﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreModel = PlayerScannerCore.Model;
using Mvvm;
using System.Collections.ObjectModel;

namespace PlayerScannerCore.ViewModel
{
    public class PlayerViewModel : ViewModelBase, IPlayerIdentifier
    {
        private PlayerViewScope _playerViewScope;
        private CoreModel.Model _model;

        //Identification info
        private int _index;
        private string _playerName;

        //Basic info
        private int _appliedShifta;
        private int _appliedDeband;
        private TimeSpan _appliedShiftaTime;
        private TimeSpan _appliedDebandTime;
        private bool _photonBlastCharge;

        //Techs
        private int _foie;
        private int _gifoie;
        private int _rafoie;
        private int _barta;
        private int _gibarta;
        private int _rabarta;
        private int _zonde;
        private int _gizonde;
        private int _razonde;
        private int _resta;
        private int _anti;
        private int _reverser;
        private int _ryuker;
        private int _shifta;
        private int _deband;
        private int _jellen;
        private int _zalure;
        private int _grants;
        private int _megid;

        //Traps
        private int _damage;
        private int _freeze;
        private int _confuse;
        private int _slow;

        //Materials
        private int _powerMaterial;
        private int _defenseMaterial;
        private int _evadeMaterial;
        private int _mindMaterial;
        private int _luckMaterial;
        private int _hpMaterial;
        private int _tpMaterial;

        //Stats
        private int _power;
        private int _basePower;
        private int _maxPower;
        private int _defense;
        private int _baseDefense;
        private int _maxDefense;
        private int _mind;
        private int _baseMind;
        private int _maxMind;
        private float _accuracy;
        private float _baseAccuracy;
        private float _maxAccuracy;
        private int _evasion;
        private int _baseEvasion;
        private int _maxEvasion;
        private int _luck;
        private int _baseLuck;
        private int _maxLuck;
        private int _hp;
        private int _tp;

        //Resistances
        private int _efr;
        private int _eic;
        private int _eth;
        private int _edk;
        private int _elt;

        //Misc
        private string _character;
        private int _guildCard;
        private int _totalExperience;
        private int _experienceTillNextLevel;
        private string _sectionId;

        public PlayerViewModel(CoreModel.Model model)
        {
            _model = model;
            InventoryViewModel = new PlayerInevntoryViewModel(model, this);
        }

        public PlayerInevntoryViewModel InventoryViewModel { get; private set; }

        public PlayerViewScope ViewScope
        {
            get { return _playerViewScope; }
            set
            {
                if (_playerViewScope != value)
                {
                    _playerViewScope = value;
                    OnPropertyChanged("ViewScope");

                    //Refresh right away for a better user experience
                    Refresh(false);
                }
            }
        }

        public int Index
        {
            get { return _index; }
            set
            {
                if (_index != value)
                {
                    _index = value;
                    OnPropertyChanged("Index");
                }
            }
        }

        public string PlayerName
        {
            get { return _playerName; }
            set
            {
                if (_playerName != value)
                {
                    _playerName = value;
                    OnPropertyChanged("PlayerName");
                }
            }
        }

        public String SectionId
        {
            get { return _sectionId; }
            set
            {
                if (_sectionId != value)
                {
                    _sectionId = value;
                    OnPropertyChanged("SectionId");
                }
            }
        }

        public int AppliedShifta
        {
            get { return _appliedShifta; }
            set
            {
                if (_appliedShifta != value)
                {
                    _appliedShifta = value;
                    OnPropertyChanged("AppliedShifta");
                }
            }
        }

        public int AppliedDeband
        {
            get { return _appliedDeband; }
            set
            {
                if (_appliedDeband != value)
                {
                    _appliedDeband = value;
                    OnPropertyChanged("AppliedDeband");
                }
            }
        }

        public TimeSpan AppliedShiftaTime
        {
            get { return _appliedShiftaTime; }
            set
            {
                if (_appliedShiftaTime != value)
                {
                    _appliedShiftaTime = value;
                    OnPropertyChanged("AppliedShiftaTime");
                }
            }
        }

        public TimeSpan AppliedDebandTime
        {
            get { return _appliedDebandTime; }
            set
            {
                if (_appliedDebandTime != value)
                {
                    _appliedDebandTime = value;
                    OnPropertyChanged("AppliedDebandTime");
                }
            }
        }

        public bool IsPhotonBlastCharged
        {
            get { return _photonBlastCharge; }
            set
            {
                if (_photonBlastCharge != value)
                {
                    _photonBlastCharge = value;
                    OnPropertyChanged("IsPhotonBlastCharged");
                }
            }
        }

        public int Foie
        {
            get { return _foie; }
            set
            {
                if (_foie != value)
                {
                    _foie = value;
                    OnPropertyChanged("Foie");
                }
            }
        }

        public int Gifoie
        {
            get { return _gifoie; }
            set
            {
                if (_gifoie != value)
                {
                    _gifoie = value;
                    OnPropertyChanged("Gifoie");
                }
            }
        }

        public int Rafoie
        {
            get { return _rafoie; }
            set
            {
                if (_rafoie != value)
                {
                    _rafoie = value;
                    OnPropertyChanged("Rafoie");
                }
            }
        }

        public int Barta
        {
            get { return _barta; }
            set
            {
                if (_barta != value)
                {
                    _barta = value;
                    OnPropertyChanged("Barta");
                }
            }
        }

        public int Gibarta
        {
            get { return _gibarta; }
            set
            {
                if (_gibarta != value)
                {
                    _gibarta = value;
                    OnPropertyChanged("Gibarta");
                }
            }
        }

        public int Rabarta
        {
            get { return _rabarta; }
            set
            {
                if (_rabarta != value)
                {
                    _rabarta = value;
                    OnPropertyChanged("Rabarta");
                }
            }
        }

        public int Zonde
        {
            get { return _zonde; }
            set
            {
                if (_zonde != value)
                {
                    _zonde = value;
                    OnPropertyChanged("Zonde");
                }
            }
        }

        public int Gizonde
        {
            get { return _gizonde; }
            set
            {
                if (_gizonde != value)
                {
                    _gizonde = value;
                    OnPropertyChanged("Gizonde");
                }
            }
        }

        public int Razonde
        {
            get { return _razonde; }
            set
            {
                if (_razonde != value)
                {
                    _razonde = value;
                    OnPropertyChanged("Razonde");
                }
            }
        }

        public int Resta
        {
            get { return _resta; }
            set
            {
                if (_resta != value)
                {
                    _resta = value;
                    OnPropertyChanged("Resta");
                }
            }
        }

        public int Anti
        {
            get { return _anti; }
            set
            {
                if (_anti != value)
                {
                    _anti = value;
                    OnPropertyChanged("Anti");
                }
            }
        }

        public int Reverser
        {
            get { return _reverser; }
            set
            {
                if (_reverser != value)
                {
                    _reverser = value;
                    OnPropertyChanged("Reverser");
                }
            }
        }

        public int Ryuker
        {
            get { return _ryuker; }
            set
            {
                if (_ryuker != value)
                {
                    _ryuker = value;
                    OnPropertyChanged("Ryuker");
                }
            }
        }

        public int Shifta
        {
            get { return _shifta; }
            set
            {
                if (_shifta != value)
                {
                    _shifta = value;
                    OnPropertyChanged("Shifta");
                }
            }
        }

        public int Deband
        {
            get { return _deband; }
            set
            {
                if (_deband != value)
                {
                    _deband = value;
                    OnPropertyChanged("Deband");
                }
            }
        }

        public int Jellen
        {
            get { return _jellen; }
            set
            {
                if (_jellen != value)
                {
                    _jellen = value;
                    OnPropertyChanged("Jellen");
                }
            }
        }

        public int Zalure
        {
            get { return _zalure; }
            set
            {
                if (_zalure != value)
                {
                    _zalure = value;
                    OnPropertyChanged("Zalure");
                }
            }
        }

        public int Grants
        {
            get { return _grants; }
            set
            {
                if (_grants != value)
                {
                    _grants = value;
                    OnPropertyChanged("Grants");
                }
            }
        }

        public int Megid
        {
            get { return _megid; }
            set
            {
                if (_megid != value)
                {
                    _megid = value;
                    OnPropertyChanged("Megid");
                }
            }
        }

        public int Damage
        {
            get { return _damage; }
            set
            {
                if (_damage != value)
                {
                    _damage = value;
                    OnPropertyChanged("Damage");
                }
            }
        }

        public int Freeze
        {
            get { return _freeze; }
            set
            {
                if (_freeze != value)
                {
                    _freeze = value;
                    OnPropertyChanged("Freeze");
                }
            }
        }

        public int Confuse
        {
            get { return _confuse; }
            set
            {
                if (_confuse != value)
                {
                    _confuse = value;
                    OnPropertyChanged("Confuse");
                }
            }
        }

        public int Slow
        {
            get { return _slow; }
            set
            {
                if (_slow != value)
                {
                    _slow = value;
                    OnPropertyChanged("Slow");
                }
            }
        }

        public int PowerMaterial
        {
            get { return _powerMaterial; }
            set
            {
                if (_powerMaterial != value)
                {
                    _powerMaterial = value;
                    OnPropertyChanged("PowerMaterial");
                }
            }
        }

        public int DefenseMaterial
        {
            get { return _defenseMaterial; }
            set
            {
                if (_defenseMaterial != value)
                {
                    _defenseMaterial = value;
                    OnPropertyChanged("DefenseMaterial");
                }
            }
        }

        public int EvadeMaterial
        {
            get { return _evadeMaterial; }
            set
            {
                if (_evadeMaterial != value)
                {
                    _evadeMaterial = value;
                    OnPropertyChanged("EvadeMaterial");
                }
            }
        }

        public int MindMaterial
        {
            get { return _mindMaterial; }
            set
            {
                if (_mindMaterial != value)
                {
                    _mindMaterial = value;
                    OnPropertyChanged("MindMaterial");
                }
            }
        }

        public int LuckMaterial
        {
            get { return _luckMaterial; }
            set
            {
                if (_luckMaterial != value)
                {
                    _luckMaterial = value;
                    OnPropertyChanged("LuckMaterial");
                }
            }
        }

        public int HpMaterial
        {
            get { return _hpMaterial; }
            set
            {
                if (_hpMaterial != value)
                {
                    _hpMaterial = value;
                    OnPropertyChanged("HpMaterial");
                }
            }
        }

        public int TpMaterial
        {
            get { return _tpMaterial; }
            set
            {
                if (_tpMaterial != value)
                {
                    _tpMaterial = value;
                    OnPropertyChanged("TpMaterial");
                }
            }
        }

        public int Power
        {
            get { return _power; }
            set
            {
                if (_power != value)
                {
                    _power = value;
                    OnPropertyChanged("Power");
                }
            }
        }

        public int BasePower
        {
            get { return _basePower; }
            set
            {
                if (_basePower != value)
                {
                    _basePower = value;
                    OnPropertyChanged("BasePower");
                }
            }
        }

        public int MaxPower
        {
            get { return _maxPower; }
            set
            {
                if (_maxPower != value)
                {
                    _maxPower = value;
                    OnPropertyChanged("MaxPower");
                }
            }
        }

        public int Defense
        {
            get { return _defense; }
            set
            {
                if (_defense != value)
                {
                    _defense = value;
                    OnPropertyChanged("Defense");
                }
            }
        }

        public int BaseDefense
        {
            get { return _baseDefense; }
            set
            {
                if (_baseDefense != value)
                {
                    _baseDefense = value;
                    OnPropertyChanged("BaseDefense");
                }
            }
        }

        public int MaxDefense
        {
            get { return _maxDefense; }
            set
            {
                if (_maxDefense != value)
                {
                    _maxDefense = value;
                    OnPropertyChanged("MaxDefense");
                }
            }
        }

        public int Mind
        {
            get { return _mind; }
            set
            {
                if (_mind != value)
                {
                    _mind = value;
                    OnPropertyChanged("Mind");
                }
            }
        }

        public int BaseMind
        {
            get { return _baseMind; }
            set
            {
                if (_baseMind != value)
                {
                    _baseMind = value;
                    OnPropertyChanged("BaseMind");
                }
            }
        }

        public int MaxMind
        {
            get { return _maxMind; }
            set
            {
                if (_maxMind != value)
                {
                    _maxMind = value;
                    OnPropertyChanged("MaxMind");
                }
            }
        }

        public float Accuracy
        {
            get { return _accuracy; }
            set
            {
                if (_accuracy != value)
                {
                    _accuracy = value;
                    OnPropertyChanged("Accuracy");
                }
            }
        }

        public float BaseAccuracy
        {
            get { return _baseAccuracy; }
            set
            {
                if (_baseAccuracy != value)
                {
                    _baseAccuracy = value;
                    OnPropertyChanged("BaseAccuracy");
                }
            }
        }

        public float MaxAccuracy
        {
            get { return _maxAccuracy; }
            set
            {
                if (_maxAccuracy != value)
                {
                    _maxAccuracy = value;
                    OnPropertyChanged("MaxAccuracy");
                }
            }
        }

        public int Evasion
        {
            get { return _evasion; }
            set
            {
                if (_evasion != value)
                {
                    _evasion = value;
                    OnPropertyChanged("Evasion");
                }
            }
        }

        public int BaseEvasion
        {
            get { return _baseEvasion; }
            set
            {
                if (_baseEvasion != value)
                {
                    _baseEvasion = value;
                    OnPropertyChanged("BaseEvasion");
                }
            }
        }

        public int MaxEvasion
        {
            get { return _maxEvasion; }
            set
            {
                if (_maxEvasion != value)
                {
                    _maxEvasion = value;
                    OnPropertyChanged("MaxEvasion");
                }
            }
        }

        public int Luck
        {
            get { return _luck; }
            set
            {
                if (_luck != value)
                {
                    _luck = value;
                    OnPropertyChanged("Luck");
                }
            }
        }

        public int BaseLuck
        {
            get { return _baseLuck; }
            set
            {
                if (_baseLuck != value)
                {
                    _baseLuck = value;
                    OnPropertyChanged("BaseLuck");
                }
            }
        }

        public int MaxLuck
        {
            get { return _maxLuck; }
            set
            {
                if (_maxLuck != value)
                {
                    _maxLuck = value;
                    OnPropertyChanged("MaxLuck");
                }
            }
        }

        public int Hp
        {
            get { return _hp; }
            set
            {
                if (_hp != value)
                {
                    _hp = value;
                    OnPropertyChanged("Hp");
                }
            }
        }

        public int Tp
        {
            get { return _tp; }
            set
            {
                if (_tp != value)
                {
                    _tp = value;
                    OnPropertyChanged("Tp");
                }
            }
        }

        public int FireResistance
        {
            get { return _efr; }
            set
            {
                if (_efr != value)
                {
                    _efr = value;
                    OnPropertyChanged("FireResistance");
                }
            }
        }

        public int IceResistance
        {
            get { return _eic; }
            set
            {
                if (_eic != value)
                {
                    _eic = value;
                    OnPropertyChanged("IceResistance");
                }
            }
        }

        public int ThunderResistance
        {
            get { return _eth; }
            set
            {
                if (_eth != value)
                {
                    _eth = value;
                    OnPropertyChanged("ThunderResistance");
                }
            }
        }

        public int DarkResistance
        {
            get { return _edk; }
            set
            {
                if (_edk != value)
                {
                    _edk = value;
                    OnPropertyChanged("DarkResistance");
                }
            }
        }

        public int LightResistance
        {
            get { return _elt; }
            set
            {
                if (_elt != value)
                {
                    _elt = value;
                    OnPropertyChanged("LightResistance");
                }
            }
        }

        public string Character
        {
            get { return _character; }
            set
            {
                if (_character != value)
                {
                    _character = value;
                    OnPropertyChanged("Character");
                }
            }
        }

        public int GuildCard
        {
            get { return _guildCard; }
            set
            {
                if (_guildCard != value)
                {
                    _guildCard = value;
                    OnPropertyChanged("GuildCard");
                }
            }
        }

        public int TotalExperience
        {
            get { return _totalExperience; }
            set
            {
                if (_totalExperience != value)
                {
                    _totalExperience = value;
                    OnPropertyChanged("TotalExperience");
                }
            }
        }

        public int ExperienceTillNextLevel
        {
            get { return _experienceTillNextLevel; }
            set
            {
                if (_experienceTillNextLevel != value)
                {
                    _experienceTillNextLevel = value;
                    OnPropertyChanged("ExperienceTillNextLevel");
                }
            }
        }

        public void Refresh(bool basicOnly)
        {
            try
            {
                //Always get this information
                var basicInfo = _model.GetBasicPlayerInfo(Index);
                AppliedShifta = basicInfo.AppliedShifta;
                AppliedDeband = basicInfo.AppliedDeband;
                AppliedShiftaTime = basicInfo.AppliedShiftaTime;
                AppliedDebandTime = basicInfo.AppliedDebandTime;
                IsPhotonBlastCharged = basicInfo.IsPhotonBlastCharged;

                if (!basicOnly)
                {
                    //Update only as much as is needed using the given scope
                    switch (ViewScope)
                    {
                    case PlayerViewScope.Inventory:
                        InventoryViewModel.Refresh();
                        break;
                    case PlayerViewScope.Techs:
                        var playerTechInfo = _model.GetPlayerTechInfo(Index);
                        Foie = playerTechInfo.Foie;
                        Gifoie = playerTechInfo.Gifoie;
                        Rafoie = playerTechInfo.Rafoie;
                        Barta = playerTechInfo.Barta;
                        Gibarta = playerTechInfo.Gibarta;
                        Rabarta = playerTechInfo.Rabarta;
                        Zonde = playerTechInfo.Zonde;
                        Gizonde = playerTechInfo.Gizonde;
                        Razonde = playerTechInfo.Razonde;
                        Resta = playerTechInfo.Resta;
                        Anti = playerTechInfo.Anti;
                        Reverser = playerTechInfo.Reverser;
                        Ryuker = playerTechInfo.Ryuker;
                        Shifta = playerTechInfo.Shifta;
                        Deband = playerTechInfo.Deband;
                        Jellen = playerTechInfo.Jellen;
                        Zalure = playerTechInfo.Zalure;
                        Grants = playerTechInfo.Grants;
                        Megid = playerTechInfo.Megid;

                        var playerTrapInfo = _model.GetPlayerTrapInfo(Index);
                        Damage = playerTrapInfo.Damage;
                        Freeze = playerTrapInfo.Freeze;
                        Confuse = playerTrapInfo.Confuse;
                        Slow = playerTrapInfo.Slow;
                        break;
                    case PlayerViewScope.Stats:
                        var playerMaterialInfo = _model.GetPlayerMaterialInfo(Index);

                        PowerMaterial = playerMaterialInfo.Power;
                        DefenseMaterial = playerMaterialInfo.Defense;
                        EvadeMaterial = playerMaterialInfo.Evasion;
                        MindMaterial = playerMaterialInfo.Mind;
                        LuckMaterial = playerMaterialInfo.Luck;
                        HpMaterial = playerMaterialInfo.Hp;
                        TpMaterial = playerMaterialInfo.Tp;

                        var playerStatsInfo = _model.GetPlayerStatsInfo(Index);

                        Power = playerStatsInfo.Power;
                        Defense = playerStatsInfo.Defense;
                        Mind = playerStatsInfo.Mind;
                        Accuracy = playerStatsInfo.Accuracy;
                        Evasion = playerStatsInfo.Evasion;
                        Luck = playerStatsInfo.Luck;
                        BasePower = playerStatsInfo.BasePower;
                        BaseDefense = playerStatsInfo.BaseDefense;
                        BaseMind = playerStatsInfo.BaseMind;
                        BaseAccuracy = playerStatsInfo.BaseAccuracy;
                        BaseEvasion = playerStatsInfo.BaseEvasion;
                        BaseLuck = playerStatsInfo.BaseLuck;
                        MaxPower = playerStatsInfo.MaxPower;
                        MaxDefense = playerStatsInfo.MaxDefense;
                        MaxAccuracy = playerStatsInfo.MaxAccuracy;
                        MaxEvasion = playerStatsInfo.MaxEvasion;
                        MaxMind = playerStatsInfo.MaxMind;
                        MaxLuck = playerStatsInfo.MaxLuck;
                        Hp = playerStatsInfo.Hp;
                        Tp = playerStatsInfo.Tp;

                        var playerResistanceInfo = _model.GetPlayerResistanceInfo(Index);

                        FireResistance = playerResistanceInfo.Efr;
                        IceResistance = playerResistanceInfo.Eic;
                        ThunderResistance = playerResistanceInfo.Eth;
                        DarkResistance = playerResistanceInfo.Edk;
                        LightResistance = playerResistanceInfo.Elt;

                        var playerMiscInfo = _model.GetPlayerMiscInfo(Index);

                        Character = playerMiscInfo.Character;
                        GuildCard = playerMiscInfo.GuildCard;
                        TotalExperience = playerMiscInfo.TotalExp;
                        ExperienceTillNextLevel = playerMiscInfo.ExpTillNextLevel;
                        SectionId = playerMiscInfo.SectionId;
                        break;
                    }
                }
            }
            catch (Exception) { } //Ignore all exceptions
        }
    }
}
